package com.jonlandrum.collections.BinarySearchTree;

public abstract class LinkedAdjustableTreeADT<T extends Comparable<T>> extends LinkedBinarySearchTree<T> {
    /**
     * Pass the constructors up to LinkedBinarySearchTree
     */
    protected LinkedAdjustableTreeADT() {
        super();
    }

    protected LinkedAdjustableTreeADT(BinarySearchNode<T> node) {
        super(node);
    }

    /**
     * Rotates left about the target node.
     *
     * @param target The node about which the rotation should occur
     * @throws IllegalStateException if the target node has no right child
     */
    protected void rotateLeft(BinarySearchNode<T> target) throws IllegalStateException {
        if (!target.hasRight()) {
            throw new IllegalStateException("Cannot rotate left at this node; no right child");
        }
        LinkedBinarySearchNode<T> temp = (LinkedBinarySearchNode<T>) target.getRight();
        if (target.hasParent()) {
            temp.setParent(target.getParent());
            if (target.isLeft()) {
                temp.getParent().setLeft(temp);
            } else {
                temp.getParent().setRight(temp);
            }
        } else {
            temp.setParent();
            this.setRoot(temp);
        }
        if (temp.hasLeft()) {
            target.setRight(temp.getLeft());
            target.getRight().setParent(target);
        } else {
            target.setRight();
        }
        target.setParent(temp);
        temp.setLeft(target);
    }

    /**
     * Rotates right about the target node.
     *
     * @param target The node about which the rotation should occur
     * @throws IllegalStateException if the target node has no left child
     */
    protected void rotateRight(BinarySearchNode<T> target) throws IllegalStateException {
        if (!target.hasLeft()) {
            throw new IllegalStateException("Cannot rotate right at this node; no left child");
        }
        LinkedBinarySearchNode<T> temp = (LinkedBinarySearchNode<T>) target.getLeft();
        if (target.hasParent()) {
            temp.setParent(target.getParent());
            if (target.isLeft()) {
                temp.getParent().setLeft(temp);
            } else {
                temp.getParent().setRight(temp);
            }
        } else {
            temp.setParent();
            this.setRoot(temp);
        }
        if (temp.hasRight()) {
            target.setLeft(temp.getRight());
            target.getLeft().setParent(target);
        } else {
            target.setLeft();
        }
        target.setParent(temp);
        temp.setRight(target);
    }
}
